#include "xdecode_task.h"
#include "xtools.h"
#include <iostream>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
#include <chrono>
using namespace std;
bool XDecodeTask::Open(AVCodecParameters *para) {
  if (!para) {
    LOGERROR("para is null");
    return false;
  }
  unique_lock<mutex> lck(mtx_);
  auto c = decode_.Create(int(para->codec_id), false);
  if (!c) {
    LOGERROR("create decoder failed");
    return false;
  }
  // 复制视频参数
  avcodec_parameters_to_context(c, para);
  decode_.set_c(c);
  if (!decode_.Open()) {
    LOGERROR("XDecodeTask::Open() failed");
    return false;
  }
  LOGINFO("open decoder success");
  return true;
}

// 责任链处理函数
void XDecodeTask::Do(AVPacket *pkt) {
  cout << "#" << flush;

  if (!pkt || pkt->stream_index != 0) // 判断是否是视频
  {
    return;
  }
  pkt_list_.Push(pkt);
}

AVFrame *XDecodeTask::GetFrame() {
  unique_lock<mutex> lock(mtx_);
  if (!need_view_ || !frame_ || !frame_->buf[0])
    return nullptr;
  auto f = av_frame_clone(frame_);
  if (!f) {
    PrintErr(AVERROR(ENOMEM));
    return nullptr;
  }
  need_view_ = false;
  return f;
}
void XDecodeTask::Main() {
  {
    unique_lock<mutex> lck(mtx_);
    if (!frame_)
      frame_ = av_frame_alloc();
  }
  while (!is_exit()) {
    auto pkt = pkt_list_.Pop();
    if (!pkt) {
      this_thread::sleep_for(1ms);
      continue;
    }
    // 发送到解码线程
    bool re = decode_.Send(pkt);
    av_packet_free(&pkt);
    if (!re) {
      LOGERROR("decode.Send() failed");
      this_thread::sleep_for(1ms);
      continue;
    }
    { // 输出
      unique_lock<mutex> lck(mtx_);
      if (decode_.Receive(frame_)) {
         cout << "@" << flush;
        need_view_ = true;
      }
    }
    this_thread::sleep_for(1ms);
  }
  {
    unique_lock<mutex> lck(mtx_);
    if (frame_)
      av_frame_free(&frame_);
  }
}
